package com.dszq.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.dszq.apis.wemedia.IWemediaClient;
import com.dszq.article.mapper.ApArticleMapper;
import com.dszq.article.service.HotArticleService;
import com.dszq.common.constants.ArticleConstants;
import com.dszq.common.redis.CacheService;
import com.dszq.model.article.pojos.ApArticle;
import com.dszq.model.article.vos.HotArticleVo;
import com.dszq.model.common.dtos.ResponseResult;
import com.dszq.model.wemedia.pojos.WmChannel;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.io.Text;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * [一句话描述该类的功能]
 *
 * @author : [Lenovo]
 * @version : [v1.0]
 * @createTime : [2024/5/3 20:30]
 */
@Service
@Slf4j
@Component
public class HotArticleServiceImpl implements HotArticleService {
    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private IWemediaClient wemediaClient;
    @Autowired
    private CacheService cacheService;
    /**
     * 计算热点文章。该方法首先获取过去5天的文章列表，然后计算每篇文章的热度分数，并为每个频道缓存前30条热点文章。
     */
    @Override
    public void computeHotArticle() {
        // 获取过去5天的日期
        Date date = DateTime.now().minusDays(5).toDate();
        // 查询过去5天的文章列表
        List<ApArticle> last5DaysArticleList = apArticleMapper.findLast5DaysArticle(date);
        // 计算文章的热度分数
        List<HotArticleVo> HotArticleList = computeHotArticleScore(last5DaysArticleList);
        // 为每个频道缓存前30条热点文章
        cache30DaysArticleByChannel(HotArticleList);
    }

    /**
     * 根据频道缓存过去30天的热点文章。该方法会为每个频道缓存前30条热点文章，以及为默认标签缓存前30条热点文章。
     *
     * @param hotArticleList 热点文章列表
     */
    private void cache30DaysArticleByChannel(List<HotArticleVo> hotArticleList) {
        // 获取所有频道
        List<WmChannel> channels = wemediaClient.findAllChannels();
        if (channels!=null&&channels.size()>0)
        {
            // 遍历每个频道，缓存热点文章
            for (WmChannel channel : channels) {
                List<HotArticleVo> hotArticleVoList = hotArticleList.stream().filter(x -> x.getChannelId().equals(channel.getId())).collect(Collectors.toList());
                sortAndCache(hotArticleVoList,ArticleConstants.HOT_ARTICLE_FIRST_PAGE+channel.getId());
            }
        }
        // 缓存默认标签的热点文章
        sortAndCache(hotArticleList,ArticleConstants.HOT_ARTICLE_FIRST_PAGE+ArticleConstants.DEFAULT_TAG);
    }

    /**
     * 对给定的文章列表进行排序并缓存。该方法会根据文章的热度分数进行降序排序，并将排序后的前30篇文章缓存起来。
     *
     * @param hotArticleVoList 文章列表
     * @param key 缓存的键
     */
    private void sortAndCache(List<HotArticleVo> hotArticleVoList, String key) {
        // 根据热度分数排序
        List<HotArticleVo> hotArticleVos = hotArticleVoList.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());
        // 仅缓存前30篇文章
        if (hotArticleVos.size()>30)
        {
             hotArticleVos = hotArticleVos.subList(0,30);
        }
        // 缓存文章列表
        cacheService.set(key, JSON.toJSONString(hotArticleVos));
    }

    /**
     * 计算文章的热度分数。该方法会根据文章的点赞数、浏览数、评论数和收藏数计算出一个热度分数。
     *
     * @param last5DaysArticleList 过去5天的文章列表
     * @return 热度文章列表
     */
    private List<HotArticleVo> computeHotArticleScore(List<ApArticle> last5DaysArticleList) {
        List<HotArticleVo> hotArticleList = new ArrayList<>();
        if (last5DaysArticleList!=null&&last5DaysArticleList.size()>0)
        {
            // 遍历文章列表，计算每篇文章的热度分数
            for (ApArticle apArticle : last5DaysArticleList) {
                HotArticleVo hotArticle = new HotArticleVo();
                BeanUtils.copyProperties(apArticle,hotArticle);
                Integer score = computeScore(hotArticle);
                hotArticle.setScore(score);
                hotArticleList.add(hotArticle);
            }
        }
        return hotArticleList;
    }
    /**
     * 计算文章的具体分值。根据文章的点赞数、浏览数、评论数和收藏数，按照预设权重计算文章的分值。
     *
     * @param apArticle 文章对象
     * @return 文章的热度分数
     */
    private Integer computeScore(ApArticle apArticle) {
        Integer scere = 0;
        // 根据点赞数、浏览数、评论数和收藏数计算分值
        if(apArticle.getLikes() != null){
            scere += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        if(apArticle.getViews() != null){
            scere += apArticle.getViews();
        }
        if(apArticle.getComment() != null){
            scere += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if(apArticle.getCollection() != null){
            scere += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return scere;
    }

}
